#!/usr/bin/env bash

prep() {
    %autosetup -n %{name}-%{version} -p1
    
    chmod +x benchtests/scripts/*.py scripts/pylint
    
    find . -type f -size 0 -o -name "*.orig" -exec rm -f {} \;
    
    touch `find . -name configure`
    
    touch locale/programs/*-kw.h
    
    ##############################################################################
    # Build glibc...
    ##############################################################################
}

build() {
    BuildFlags="-O2 -g"
    BuildFlags="$BuildFlags -DNDEBUG"
    
    %ifarch aarch64
    BuildFlags="$BuildFlags -mno-outline-atomics"
    %endif
    
    reference=" \
            "-Wp,-D_GLIBCXX_ASSERTIONS" \
            "-fasynchronous-unwind-tables" \
            "-fstack-clash-protection" \
            "-funwind-tables" \
            "-m31" \
            "-m32" \
            "-m64" \
            "-march=haswell" \
            "-march=i686" \
            "-march=x86-64" \
            "-march=z13" \
            "-march=z14" \
            "-march=zEC12" \
            "-mfpmath=sse" \
            "-msse2" \
            "-mstackrealign" \
            "-mtune=generic" \
            "-mtune=z13" \
            "-mtune=z14" \
            "-mtune=zEC12" \
            "-specs=/usr/lib/rpm/%{_vendor}/%{_vendor}-annobin-cc1" "
    
    for flag in $RPM_OPT_FLAGS $RPM_LD_FLAGS ; do
    if echo "$reference" | grep -q -F " $flag " ; then
    BuildFlags="$BuildFlags $flag"
    fi
    done
    
    %define glibc_make_flags_as ASFLAGS="-g -Wa,--generate-missing-build-notes=yes"
    %define glibc_make_flags %{glibc_make_flags_as}
    
    EnableKernel="--enable-kernel=%{enablekernel}"
    
    builddir=build-%{target}
    rm -rf $builddir
    mkdir $builddir
    pushd $builddir
    configure_builddir
    { cat config.log; false; }
    
    make %{?build_make_builddir_flags} %{?_smp_mflags} -O -r %{glibc_make_flags}
    popd
    
    ##############################################################################
    # Build libpthread-2.17.so
    ##############################################################################
    %if %{with compat_2_17}
    cd nptl_2_17
    sh build_libpthread-2.17.so.sh %{_target_cpu} $builddir
    cd ..
    %endif
    
    ##############################################################################
    # Install glibc...
    ##############################################################################
}

configure_builddir() {
    ../configure CC="%GCC" CXX="%GXX" CFLAGS="$BuildFlags" \
    ||
    
}

install() {
    %ifarch riscv64
    for d in $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT/%{_lib}; do
    mkdir -p $d
    (cd $d && ln -sf . lp64d)
    done
    %endif
    
    make %{?_smp_mflags} install_root=$RPM_BUILD_ROOT install -C build-%{target}
    
    pushd build-%{target}
    
    make %{?_smp_mflags} install_root=$RPM_BUILD_ROOT \
    	install-locale-files -C ../localedata objdir=`pwd`
    popd
    
    python3 %{SOURCE7} $RPM_BUILD_ROOT/usr/lib/locale
    
    rm -f $RPM_BUILD_ROOT/%{_libdir}/libNoVersion*
    rm -f $RPM_BUILD_ROOT/%{_lib}/libNoVersion*
    rm -f $RPM_BUILD_ROOT/%{_lib}/libnss1-*
    rm -f $RPM_BUILD_ROOT/%{_lib}/libnss-*.so.1
    rm -f $RPM_BUILD_ROOT/{usr/,}sbin/sln
    
    mkdir -p $RPM_BUILD_ROOT/var/cache/ldconfig
    truncate -s 0 $RPM_BUILD_ROOT/var/cache/ldconfig/aux-cache
    
    $RPM_BUILD_ROOT/sbin/ldconfig -N -r $RPM_BUILD_ROOT
    
    # Install info files
    %if %{with docs}
    # Move the info files if glibc installed them into the wrong location.
    if [ -d $RPM_BUILD_ROOT%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then
    mkdir -p $RPM_BUILD_ROOT%{_infodir}
    mv -f $RPM_BUILD_ROOT%{_prefix}/info/* $RPM_BUILD_ROOT%{_infodir}
    rm -rf $RPM_BUILD_ROOT%{_prefix}/info
    fi
    
    # Compress all of the info files.
    gzip -9nvf $RPM_BUILD_ROOT%{_infodir}/libc*
    
    %else
    rm -f $RPM_BUILD_ROOT%{_infodir}/dir
    rm -f $RPM_BUILD_ROOT%{_infodir}/libc.info*
    %endif
    
    # Create all-packages libc.lang
    olddir=`pwd`
    pushd $RPM_BUILD_ROOT%{_prefix}/lib/locale
    rm -f locale-archive
    $olddir/build-%{target}/elf/ld.so \
            --library-path $olddir/build-%{target}/ \
            $olddir/build-%{target}/locale/localedef \
            --alias-file=$olddir/intl/locale.alias	\
            --prefix $RPM_BUILD_ROOT --add-to-archive \
            eo *_*
    %{find_lang} libc
    # In the past, locale-archive is provided by common.
    # In the current version, locale-archive is provided by locale-archive.
    # Due to the change of the packing mode, the locale-archive fails to be
    # replaced during the upgrade. Therefore, a backup file is required to
    # replace the locale-archive.
    mv locale-archive locale-archive.update
    
    $olddir/build-%{target}/elf/ld.so \
            --library-path $olddir/build-%{target}/ \
            $olddir/build-%{target}/locale/localedef \
            --alias-file=$olddir/intl/locale.alias  \
            --prefix $RPM_BUILD_ROOT --add-to-archive \
            zh_* en_*
    mv locale-archive locale-archive.default
    popd
    mv  $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang .
    
    # Install configuration files for services
    install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/nsswitch.conf
    
    # This is for compat-2.17
    %if %{with compat_2_17}
    install -p -m 755  build-%{target}/nptl/libpthread-2.17.so $RPM_BUILD_ROOT%{_libdir}
    # Build an empty libpthread_nonshared.a for compatiliby with applications
    # that have old linker scripts that reference this file.
    ar cr $RPM_BUILD_ROOT/%{_prefix}/%{_lib}/libpthread_nonshared.a
    %endif
    
    # This is for ncsd - in glibc 2.2
    install -m 644 nscd/nscd.conf $RPM_BUILD_ROOT/etc
    mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir}
    install -m 644 %{SOURCE1} %{buildroot}%{_tmpfilesdir}
    mkdir -p $RPM_BUILD_ROOT/lib/systemd/system
    install -m 644 nscd/nscd.service nscd/nscd.socket $RPM_BUILD_ROOT/lib/systemd/system
    
    # Include ld.so.conf
    echo 'include ld.so.conf.d/*.conf' > $RPM_BUILD_ROOT/etc/ld.so.conf
    truncate -s 0 $RPM_BUILD_ROOT/etc/ld.so.cache
    chmod 644 $RPM_BUILD_ROOT/etc/ld.so.conf
    mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d
    mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
    truncate -s 0 $RPM_BUILD_ROOT/etc/sysconfig/nscd
    truncate -s 0 $RPM_BUILD_ROOT/etc/gai.conf
    
    # Include %{_libdir}/gconv/gconv-modules.cache
    truncate -s 0 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache
    chmod 644 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache
    
    # Remove any zoneinfo files; they are maintained by tzdata.
    rm -rf $RPM_BUILD_ROOT%{_prefix}/share/zoneinfo
    
    touch -r %{SOURCE0} $RPM_BUILD_ROOT/etc/ld.so.conf
    touch -r inet/etc.rpc $RPM_BUILD_ROOT/etc/rpc
    
    # Lastly copy some additional documentation for the packages.
    rm -rf documentation
    mkdir documentation
    cp timezone/README documentation/README.timezone
    cp posix/gai.conf documentation/
    
    %if %{with benchtests}
    # Build benchmark binaries.  Ignore the output of the benchmark runs.
    pushd build-%{target}
    make BENCH_DURATION=1 bench-build
    popd
    
    # Copy over benchmark binaries.
    mkdir -p $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests
    cp $(find build-%{target}/benchtests -type f -executable) $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
    
    #makefile.
    for b in %{SOURCE3} %{SOURCE4}; do
    cp $b $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
    done
    
    #comparison scripts.
    for i in benchout.schema.json compare_bench.py import_bench.py validate_benchout.py; do
    cp benchtests/scripts/$i $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
    done
    %endif
    
    pushd locale
    ln -s programs/*.gperf .
    popd
    
    pushd iconv
    ln -s ../locale/programs/charmap-kw.gperf .
    popd
    
    %if %{with docs}
    rm -f $RPM_BUILD_ROOT%{_infodir}/dir
    %endif
    
    mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd
    touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services}
    touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid}
    
    mkdir -p $RPM_BUILD_ROOT%{_libdir}
    mv -f $RPM_BUILD_ROOT/%{_lib}/lib{pcprofile,memusage}.so \
    	$RPM_BUILD_ROOT%{_libdir}
    
    # Strip all of the installed object files.
    strip -g $RPM_BUILD_ROOT%{_libdir}/*.o
    
    # create a null libpthread static link for compatibility.
    pushd $RPM_BUILD_ROOT%{_prefix}/%{_lib}/
    rm libpthread.a
    ar rc libpthread.a
    popd
    
    for i in $RPM_BUILD_ROOT%{_prefix}/bin/{xtrace,memusage}; do
    %if %{with bootstrap}
    test -w $i || continue
    %endif
    sed -e 's~=/%{_lib}/libpcprofile.so~=%{_libdir}/libpcprofile.so~' \
          -e 's~=/%{_lib}/libmemusage.so~=%{_libdir}/libmemusage.so~' \
          -e 's~='\''/\\\$LIB/libpcprofile.so~='\''%{_prefix}/\\$LIB/libpcprofile.so~' \
          -e 's~='\''/\\\$LIB/libmemusage.so~='\''%{_prefix}/\\$LIB/libmemusage.so~' \
          -i $i
    done
    
    touch master.filelist
    touch glibc.filelist
    touch common.filelist
    touch devel.filelist
    touch nscd.filelist
    touch nss_modules.filelist
    touch nss-devel.filelist
    %ifnarch loongarch64
    touch libnsl.filelist
    %endif
    touch debugutils.filelist
    touch benchtests.filelist
    touch help.filelist
    %if %{with compat_2_17}
    touch compat-2.17.filelist
    %endif
    
    {
    find $RPM_BUILD_ROOT \( -type f -o -type l \) \
           \( \
         -name etc -printf "\%\%\%\%config " -o \
         -name gconv-modules \
         -printf "\%\%\%\%verify(not md5 size mtime) \%\%\%\%config(noreplace) " -o \
         -name gconv-modules.cache \
         -printf "\%\%\%\%verify(not md5 size mtime) " \
         , \
         ! -path "*/lib/debug/*" -printf "/\%\%P\n" \)
    
    find $RPM_BUILD_ROOT -type d \
           \( -path '*%{_prefix}/share/locale' -prune -o \
           \( -path '*%{_prefix}/share/*' \
    %if %{with docs}
    ! -path '*%{_infodir}' -o \
    %endif
    -path "*%{_prefix}/include/*" \
           \) -printf "\%\%\%\%dir /\%\%P\n" \)
    } | {
    sed -e '\,.*/share/locale/\([^/_]\+\).*/LC_MESSAGES/.*\.mo,d' \
          -e '\,.*/share/i18n/locales/.*,d' \
          -e '\,.*/share/i18n/charmaps/.*,d' \
          -e '\,.*/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \
          -e '\,.*%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \
    %if %{with compat_2_17}
    -e '\,.*%{_libdir}/libpthread-2.17.so,d' \
          -e '\,.*%{_libdir}/libpthread_nonshared.a,d' \
    %endif
    -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d'
    } | sort > master.filelist
    
    chmod 0444 master.filelist
    
    ##############################################################################
    # glibc - The GNU C Library (glibc) core package.
    ##############################################################################
    cat master.filelist \
        | grep -v \
        -e '%{_infodir}' \
        -e '%{_libdir}/lib.*_p.a' \
        -e '%{_prefix}/include' \
        -e '%{_libdir}/lib.*\.a' \
            -e '%{_libdir}/.*\.o' \
        -e '%{_libdir}/lib.*\.so' \
        -e 'nscd' \
        -e '%{_prefix}/bin' \
        -e '%{_prefix}/lib/locale' \
        -e '%{_prefix}/sbin/[^i]' \
        -e '%{_prefix}/share' \
        -e '/var/db/Makefile' \
        -e '/libnss_.*\.so[0-9.]*$' \
    %ifnarch loongarch64
    -e '/libnsl' \
    %endif
    -e 'glibc-benchtests' \
        -e 'aux-cache' \
        > glibc.filelist
    
    for module in compat files dns; do
    cat master.filelist \
        | grep -E \
        -e "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \
        >> glibc.filelist
    done
    
    echo  '%{_libdir}/libmemusage.so' >> glibc.filelist
    echo  '%{_libdir}/libpcprofile.so' >> glibc.filelist
    
    ##############################################################################
    # glibc "common" sub-package
    ##############################################################################
    grep '%{_prefix}/bin' master.filelist > common.filelist
    grep '%{_prefix}/sbin' master.filelist \
           | grep -v '%{_prefix}/sbin/iconvconfig' \
    	| grep -v 'nscd' >> common.filelist
    
    grep '%{_prefix}/share' master.filelist \
    	| grep -v \
    	-e '%{_prefix}/share/info/libc.info.*' \
    	-e '\%\%dir %{prefix}/share/info' \
    	-e '\%\%dir %{prefix}/share' \
    	>> common.filelist
    
    ###############################################################################
    # glibc "devel" sub-package
    ###############################################################################
    %if %{with docs}
    grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > help.filelist
    %endif
    
    grep '%{_libdir}/lib.*\.a' master.filelist \
      | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \
      >> devel.filelist
    
    grep '%{_libdir}/.*\.o' < master.filelist >> devel.filelist
    grep '%{_libdir}/lib.*\.so' < master.filelist >> devel.filelist
    
    sed -i -e '\,/libnss_[a-z]*\.so$,d' devel.filelist
    
    grep '%{_prefix}/include' < master.filelist >> devel.filelist
    
    grep '%{_libdir}/lib.*\.a' < master.filelist \
      | grep -v '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \
      >> devel.filelist
    
    
    ##############################################################################
    # glibc "nscd" sub-package
    ##############################################################################
    echo '%{_prefix}/sbin/nscd' > nscd.filelist
    
    ##############################################################################
    # nss modules sub-package
    ##############################################################################
    grep -E "/libnss_(db|hesiod)(\.so\.[0-9.]+|-[0-9.]+\.so)$" \
    master.filelist > nss_modules.filelist
    
    ##############################################################################
    # nss-devel sub-package
    ##############################################################################
    grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist
    
    ##############################################################################
    # libnsl subpackage
    ##############################################################################
    %ifnarch loongarch64
    grep -E '/libnsl\.so\.[0-9]+$' master.filelist > libnsl.filelist
    test $(wc -l < libnsl.filelist) -eq 1
    %endif
    ##############################################################################
    # glibc debugutils sub-package
    ##############################################################################
    cat > debugutils.filelist <<EOF
    %if %{without bootstrap}
    %{_prefix}/bin/memusage
    %{_prefix}/bin/memusagestat
    %endif
    %{_prefix}/bin/mtrace
    %{_prefix}/bin/pcprofiledump
    %{_prefix}/bin/xtrace
    EOF
    
    %if %{with benchtests}
    ##############################################################################
    # glibc benchtests sub-package
    ##############################################################################
    find build-%{target}/benchtests -type f -executable | while read b; do
    echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)"
    done > benchtests.filelist
    # ... and the makefile.
    for b in %{SOURCE3} %{SOURCE4}; do
    echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" >> benchtests.filelist
    done
    # ... and finally, the comparison scripts.
    echo "%{_prefix}/libexec/glibc-benchtests/benchout.schema.json" >> benchtests.filelist
    echo "%{_prefix}/libexec/glibc-benchtests/compare_bench.py*" >> benchtests.filelist
    echo "%{_prefix}/libexec/glibc-benchtests/import_bench.py*" >> benchtests.filelist
    echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.filelist
    %endif
    
    %if %{with compat_2_17}
    ##############################################################################
    # glibc compat-2.17 sub-package
    ##############################################################################
    echo "%{_libdir}/libpthread-2.17.so" >> compat-2.17.filelist
    echo "%{_libdir}/libpthread_nonshared.a" >> compat-2.17.filelist
    %endif
    
    reliantlib=""
    
    function findReliantLib()
    {
    local library=$1
    reliantlib=$(readelf -d $library | grep "(NEEDED)" | awk -F "Shared library" '{print $2}')$reliantlib
    }
    
    # remove gconv rpath/runpath
    function removeLoadPath()
    {
    local file=$1
    local rpathInfo=$(chrpath -l $file | grep "RPATH=")
    local runpathInfo=$(chrpath -l $file | grep "RUNPATH=")
    
    local currPath=""
    if [ x"$rpathInfo" != x"" ]; then
    currPath=$(echo $rpathInfo | awk -F "RPATH=" '{print $2}')
    fi
    
    if [ x"$runpathInfo" != x"" ]; then
    currPath=$(echo $runpathInfo | awk -F "RUNPATH=" '{print $2}')
    fi
    
    if [ x"$currPath" == x"\$ORIGIN" ]; then
    chrpath -d $file
    
    findReliantLib $file
    fi
    }
    
    set +e
    
    # find and remove RPATH/RUNPATH
    for file in $(find $RPM_BUILD_ROOT%{_libdir}/gconv/ -name "*.so" -exec file {} ';' | grep "\<ELF\>" | awk -F ':' '{print $1}')
    do
    removeLoadPath $file
    done
    
    function createSoftLink()
    {
    # pick up the dynamic libraries and create softlink for them
    local tmplib=$(echo $reliantlib | sed 's/://g' | sed 's/ //g' | sed 's/\[//g' | sed 's/]/\n/g' | sort | uniq)
    
    for temp in $tmplib
    do
    if [ -f "$RPM_BUILD_ROOT%{_libdir}/gconv/$temp" ]; then
    ln -sf %{_libdir}/gconv/$temp $RPM_BUILD_ROOT%{_libdir}/$temp
    echo %{_libdir}/$temp >> glibc.filelist
    fi
    done
    }
    
    # create soft link for the reliant libraries
    createSoftLink
    set -e
    
    ##############################################################################
    # Run the glibc testsuite
    ##############################################################################
}

check() {
    %if %{with testsuite}
    omit_testsuite() {
    while read testsuite; do
    testsuite_escape=$(echo "$testsuite" | \
                           sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/g')
    sed -i "/${testsuite_escape}/d" rpmbuild.tests.sum.not-passing
    done
    }
    
    # Increase timeouts
    export TIMEOUTFACTOR=16
    parent=$$
    echo ====================TESTING=========================
    
    # Default libraries.
    pushd build-%{target}
    make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2
    test -s tests.sum
    
    # This hides a test suite build failure, which should be fatal.  We
    # check "Summary of test results:" below to verify that all tests
    # were built and run.
    if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then
    echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2
    exit 1
    fi
    grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true
    
    # Delete the testsuite from the whitelist
    cat %{SOURCE8} | \
    	grep -v "^$\|^#" | \
    	awk -F':' '{if($2 == "" || $2 ~ /'%{_target_cpu}'/ ) {print $1}}' |\
    	omit_testsuite
    
    set +x
    if test -s rpmbuild.tests.sum.not-passing ; then
    echo ===================FAILED TESTS===================== >&2
    echo "Target: $(basename "$(pwd)")" >& 2
    cat rpmbuild.tests.sum.not-passing >&2
    while read failed_code failed_test ; do
    for suffix in out test-result ; do
    if test -e "$failed_test.$suffix"; then
    echo >&2
    echo "=====$failed_code $failed_test.$suffix=====" >&2
    cat -- "$failed_test.$suffix" >&2
    echo >&2
    fi
    done
    done <rpmbuild.tests.sum.not-passing
    %if 0%{?glibc_abort_after_test_fail}
    exit 1
    %endif
    fi
    
    # Unconditonally dump differences in the system call list.
    echo "* System call consistency checks:" >&2
    cat misc/tst-syscall-list.out >&2
    set -x
    popd
    
    echo ====================TESTING END=====================
    PLTCMD='/^Relocation section .*\(\.rela\?\.plt\|\.rela\.IA_64\.pltoff\)/,/^$/p'
    echo ====================PLT RELOCS LD.SO================
    readelf -Wr $RPM_BUILD_ROOT/%{_lib}/ld-*.so | sed -n -e "$PLTCMD"
    echo ====================PLT RELOCS LIBC.SO==============
    readelf -Wr $RPM_BUILD_ROOT/%{_lib}/libc-*.so | sed -n -e "$PLTCMD"
    echo ====================PLT RELOCS END==================
    
    pushd build-%{target}
    LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true
    
    %if %{with valgrind}
    elf/ld.so --library-path .:elf:nptl:dlfcn \
    	/usr/bin/valgrind --error-exitcode=1 \
    	elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true
    %endif
    popd
    
    %endif # %{run_glibc_tests}
    
    ##############################################################################
    # Install and uninstall scripts
    ##############################################################################
}

